﻿using Haidou.Wpf.Native.External;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Interop;

namespace Haidou.Wpf.Native.Helpers
{
	public static class Windows
	{
	


		/// <summary>
		/// Gets the z-order for one or more windows atomically with respect to each other. 
		/// In Windows, smaller z-order is higher. If the window is not top level, the z order is returned as -1. 
		/// </summary>
		public static int[] GetZOrder(params IntPtr[] hWnds)
		{
			int[] z = new int[hWnds.Length];
			for (int i = 0; i < hWnds.Length; i++)
				z[i] = -1;

			int index = 0;
			int numRemaining = hWnds.Length;

			User32.EnumWindows((wnd, param) =>
			{
				int searchIndex = Array.IndexOf(hWnds, wnd);

				if (searchIndex != -1)
				{
					z[searchIndex] = index;
					numRemaining--;
					if (numRemaining == 0) return false;
				}

				index++;
				return true;
			}, IntPtr.Zero);

			return z;
		}

		/// <summary>
		/// 从给定进程中获取所有一级窗口句柄。
		/// The windows must be visible.
		/// </summary>
		public static List<IntPtr> GetWindowHandlesFromProcess(Process process)
		{
			List<IntPtr> list = new List<IntPtr>();

			//Each thread can create a window.
			foreach (ProcessThread info in process.Threads)
			{
				//With given thread ID, search for windows.
				IntPtr[] windows = GetWindowHandlesForThread((IntPtr)info.Id);

				if (windows != null)
					list.AddRange(windows);
			}

			return list;
		}

		private static IntPtr[] GetWindowHandlesForThread(IntPtr threadHandle)
		{
			List<IntPtr> results = new List<IntPtr>();

			//Enumerate all top level desktop windows.
			User32.EnumWindows(delegate (IntPtr window, IntPtr thread)
			{
				//Get the ID of the thread that created the window.
				uint threadId = User32.GetWindowThreadProcessId(window, out _);

				//Check if the selected thread created this window.
				if ((IntPtr)threadId != thread)
					return true;

				if (!User32.IsWindowVisible(window))
					return true;

				results.Add(window);
				return true;
			}, threadHandle);

			return results.ToArray();
		}

		
	
	
	}
}
